﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Atomic.Common;
using System.Linq.Expressions;
using NHibernate;
using NHibernate.Linq;

#region 版本信息
/*********************************************
 * 作者：杜一博
 * 创建日期：2012/8/1 23:26:10
 *********************************************
 * 修改：
 * 修改日期：
 * 修改说明：
 *********************************************/
#endregion

namespace Atomic.Db
{
    /// <summary>
    /// 对NHibernate进行一次初级封装，泛型方法实现常用的CRUD方法，避免重复编写代码
    /// </summary>
    public abstract class BaseDAL<T> : ErrorImpl, IBaseDAL<T>, IDisposable
    {
        /// <summary>
        /// 数据库会话
        /// </summary>
        protected ISession session
        {
            get
            {
                if (_session == null || !_session.IsOpen)
                {
                    _session = HibernateHelper.GetSession();
                }
                return _session;
            }
            set
            {
                this._session = value;
            }
        }
        private ISession _session;

        /// <summary>
        /// 默认构造方法，使用默认session进行数据库操作
        /// </summary>
        public BaseDAL()
        {
            try
            {

            this.session = HibernateHelper.GetSession();
            }
            catch (Exception e)
            {

                throw e;
            }
        }
        /// <summary>
        /// 外部传入session，一般在事务处理的情况下使用，也兼容非事务session
        /// </summary>
        /// <param name="session">开启事务的session</param>
        public BaseDAL(ISession session)
        {
            this.session = session;
        }

        ~BaseDAL()
        {
            if (session != null)
            {
                session.Dispose();
            }
        }

        /// <summary>
        /// 进行对象验证，并新建对象
        /// </summary>
        /// <param name="entity">要创建的对象信息</param>
        public virtual object Add(T entity)
        {
            object o = session.Save(entity);
            session.Flush();
            return o;
        }

        /// <summary>
        /// 删除对象，如果对象配置了Hibernate级联，则会进行级联删除
        /// </summary>
        /// <param name="id">要删除对象的主键</param>
        public virtual void Remove(object id)
        {
            T entity = session.Get<T>(id);
            session.Delete(entity);
            session.Flush();
        }

        /// <summary>
        /// 分页查询数据，按数据库默认顺序排序查询结果
        /// </summary>
        /// <param name="pager">分页参数</param>
        /// <param name="predicate">查询筛选条件</param>
        /// <returns>分页查询结果</returns>
        public virtual Pager<T> GetPager(Pager pager, Expression<Func<T, bool>> predicate = null)
        {
            Pager<T> p = null;
            //按条件确定是否分页查询
            if (pager == null)
            {
                p = new Pager<T>();
                //查询筛选条件
                if (predicate == null)
                {
                    p.Records = session.Query<T>()
                        .ToList();
                }
                else
                {
                    p.Records = session.Query<T>()
                        .Where(predicate)
                        .ToList();
                }
                p.Total = p.Records.Count;
            }
            else
            {
                //查询筛选条件
                if (predicate == null)
                {
                    p = new Pager<T>
                    {
                        Records = session.Query<T>()
                            .Skip((pager.Index - 1) * pager.Rows)
                            .Take(pager.Rows)
                            .ToList()
                    };
                    p.Total = session.Query<T>()
                            .Count();
                }
                else
                {
                    p = new Pager<T>
                    {
                        Records = session.Query<T>()
                            .Where(predicate)
                            .Skip((pager.Index - 1) * pager.Rows)
                            .Take(pager.Rows)
                            .ToList()
                    };
                    p.Total = session.Query<T>()
                            .Where(predicate)
                            .Count();
                }
            }
            return p;
        }

        /// <summary>
        /// 更新对象
        /// </summary>
        /// <param name="entity">更新对象</param>
        /// <param name="id">更新对象的主键</param>
        public virtual void Update(T entity, object id)
        {
            session.Update(entity, id);
            session.Flush();
        }

        /// <summary>
        /// 条件查询列表
        /// </summary>
        /// <param name="predicate">查询条件</param>
        public virtual List<T> GetList(Expression<Func<T, bool>> predicate = null)
        {
            if (null == predicate)
            {
                return session.Query<T>()
                    .ToList<T>();
            }
            else
            {
                return session.Query<T>()
                    .Where(predicate)
                    .ToList<T>();
            }
        }

        /// <summary>
        /// 通过主键获取对象信息
        /// </summary>
        /// <param name="id">主键ID</param>
        /// <returns>对象信息</returns>
        public virtual T Get(object id)
        {
            return session.Get<T>(id);
        }

        /// <summary>
        /// 条件查询一条记录
        /// </summary>
        /// <param name="predicate">查询条件</param>
        /// <returns>满足条件的一条记录或null</returns>
        public virtual T Get(Expression<Func<T, bool>> predicate)
        {
            return session.Query<T>()
                .Where(predicate)
                .FirstOrDefault();
        }


        /// <summary>
        /// 是否存在指定条件的记录
        /// </summary>
        /// <param name="predicate">查询条件</param>
        /// <returns>是否存在指定记录信息</returns>
        public virtual bool Exist(Expression<Func<T, bool>> predicate = null)
        {
            return
                session.Query<T>()
                    .Where(predicate)
                    .Count() > 0;   //是否存在记录
        }

        public void Dispose()
        {
        }
    }
}
